/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package master_server;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author Karen & François & Renaud
 */
public class HThreadClient extends Thread {

    InetAddress ia;
    HiberMastermind accesBdd;
    HashMap<String, SecretCode> joueurs;
    ArrayList<SecretCode> parties;
    Protocol connector;

    public HThreadClient(HashMap<String, SecretCode> joueursCo, ArrayList<SecretCode> parties, HiberMastermind bdd, Socket s) throws IOException {

        this.parties = parties;
        joueurs = joueursCo;
        accesBdd = bdd;
        connector = new Protocol(s);
        //ia = connector.getSocket().getInetAddress() ;
    }

    @Override
    public void run() {
        System.out.println(" ");
        System.out.println("nouveau Thread");
        try {
            //  connector.connect(); // faut pas oublier ce truc

            System.out.println(" Hostname du client : " + connector.getHostNameClient());
            System.out.println(" HostAddress du client : " + connector.getHostAdressClient()); // infos sur le client
            System.out.println(" Port local : " + connector.getLocalPort());
            System.out.println(" Port distant : " + connector.getDistPort());
            System.out.println(" ");
            System.out.println("Thread numero = [" + this.getName() + "]");

            String choix = connector.RedOneString();
            System.out.println("choix reçu " + choix);

            // ------ choix d'actions ....  
            switch (choix) {
                // --- les messages qu'un client peut envoyer 
                // --- no connect 
                case "nouvelle partie":
                    newPartie();
                    break;  // creation d'une nouvelle partie
                case "nouvelle configuration":
                    reNewGame();
                    break; // nouvelle configuration
                case "meme configuration":
                    reMConfig();
                    break; // même config new code
                case "verifier combinaison":
                    verifCombi();
                    break; // verification de combi  
                case "verifier combinaison int":
                    verifCombi();
                    break; // verification de combi     
                case "win":
                    win();
                    break;      // utilisateur existant commence une autre partie.

                // ---  connect 
                case "newUser":
                    newUser();
                    ;
                    break;  // creation d'un nev user dans la BD
                case "log In":
                    logIn();
                    ;
                    break;     // verif existance de user et son pass dans la BD
                case "getUserStats":
                    getUserStats();
                    break;   //demande de stats d'un user
                case "verifier combinaison user":
                    verifUserCombi();
                    break;    // demande de virs de la combi d'un user donné
                case "creation partie":
                    newUserPartie();
                    break;   //creation d'une partie dans hashMap

                // ---  Global 
                case "getStats":
                    getStats();
                    break;       // demande de stats 

                //    default : break;    
            }

        } catch (IOException ex) {
            System.out.println("catch  " + ex);
        }
        try {
            connector.stopTCP();
        } catch (IOException ex) {
            System.out.println("catch2  " + ex);
        }
        System.out.println("Fin du Thread");
    }
    // converti le flux en une combinaison // deplacer vers protocol?

    public Bille[] toBille(String flux) {
        String[] trans = flux.split("-");
        Bille[] combi = new Bille[trans.length];
        for (int i = 0; i < combi.length; i++) {
            combi[i] = Bille.valueOf(trans[i]);
        }
        return combi;
    }

    private void newPartie() throws IOException {
        // reception des parametres  
        System.out.println("demande nouvelle partie reçu, creation d'une partie ");
        int choixBilles = connector.RedOneInt();
        int colors = connector.RedOneInt();
        System.out.println("avec parametres= choixBilles: " + choixBilles + ", colors: " + colors);
        // creation d'un new partie

        parties.add(new SecretCode(choixBilles, colors));

        System.out.println("Id de la nouvelle partie => " + (parties.size() - 1));
        System.out.print("Son code secret est => ");
        parties.get(parties.size() - 1).printScode();
        System.out.println();

        // envoie ID vers client
        connector.writeOneInt(parties.size() - 1);


    }

    private void verifCombi() throws IOException {


        int IdPartie = connector.RedOneInt();
        System.out.println(" Debut de verification !");
        System.out.println(" de la partie => " + IdPartie);

        // reception de la combi 
        String fluxRecu = connector.RedOneString();
        System.out.println(" Reçu de la combinaison joueur... " + fluxRecu);

        // convertion vers  BILLE[]
        Bille[] combiJoueur = toBille(fluxRecu);
        Pions out = parties.get(IdPartie).verifCombinaison(combiJoueur);

        System.out.println(" Resultat de la verification : N = " + out.getNoir() + " B = " + out.getBlanc());

        connector.writeOneString(String.valueOf(out.getNoir()));
        connector.writeOneString(String.valueOf(out.getBlanc()));

        if (parties.get(IdPartie).estGagnant()) {
            connector.writeOneString("true");
        } else {
            connector.writeOneString("false");
        }


        System.out.println(" Envoi du resultat au joueur...");
    }

    private void reNewGame() throws IOException {
        // lecture d'id

        int idPartie = connector.RedOneInt();
        System.out.println("nouvelle configuration poour la partie " + idPartie);
        int choixBilles = connector.RedOneInt();
        int colors = connector.RedOneInt();
        parties.set(idPartie, new SecretCode(choixBilles, colors));
        System.out.print("Son nouveau code secret est => ");
        parties.get(idPartie).printScode();
        System.out.println();
    }
    // ------------------ à ajouter  dans client
    //  reconstruir le code secret pour une partie sans changer les configuration

    private void reMConfig() throws IOException {
        int idPartie = connector.RedOneInt();
        System.out.println("nouveau code pour la partie " + idPartie);
        parties.get(idPartie).reBuildCode();
        System.out.print("Son nouveau code secret est => ");
        parties.get(idPartie).printScode();
        System.out.println();
    }

    private void win() throws IOException {
        int idPartie = connector.RedOneInt();
        System.out.println("recu demande WIN de ID" + idPartie);
        System.out.println(parties.get(idPartie).estGagnant());
        if (parties.get(idPartie).estGagnant() == true) { // ==> true
            connector.writeOK();
        } else {
            connector.writeNOK();
        }

    }

    // creation d'un new user dans la BD
    private void newUser() throws IOException {

        String user = connector.RedOneString();
        String pass = connector.RedOneString();

        System.out.println("NOM =" + user + " pass =" + pass);

        if (accesBdd.insererJoueur(user, pass)) { // tentative d'insertion = true ok false user existant
            connector.writeOK();
        } else {
            connector.writeNOK();
        }


    }

    private void logIn() throws IOException {

        String user = connector.RedOneString();
        String pass = connector.RedOneString();

        if (accesBdd.joueurExistant(user, pass)) { // verif de login et pass
            connector.writeOK();
        } else {
            connector.writeNOK();
        }


    }
    // verification d'une partie (hashmap)

    private void verifUserCombi() throws IOException {

        String user = connector.RedOneString();

        System.out.println(" Debut de verification !");
        System.out.println(" user => " + user);

        // je récupére une copie de l'objet secret code pour eviter les acces innutiles
        SecretCode original = joueurs.get(user);

        // reception de la combi 
        String fluxRecu = connector.RedOneString();
        System.out.println(" Reçu de la combinaison joueur... " + fluxRecu);
        int numTourC = connector.RedOneInt();
        System.out.println(" tour de la partie " + numTourC);

        // convertion vers  BILLE[]
        Bille[] combiJoueur = toBille(fluxRecu);
        // recuperation des pions avec la function verifcombi
        Pions out = original.verifCombinaison(combiJoueur);

        connector.writeOneString(String.valueOf(out.getNoir()));
        connector.writeOneString(String.valueOf(out.getBlanc()));

        // si partie gagniante  alors 
        //  System.out.println(" Resultat de la verification : N = "+out.getNoir()+" B = "+out.getBlanc());

        if (original.estGagnant()) {
            int idC;
            connector.writeOneString("true"); // envoie au client
            idC = accesBdd.getIdconf(original.getColons(), original.getColors());
            int score = etablirScore(original.getNbTent(), numTourC)*idC;
            connector.writeOneString(String.valueOf(score)); // envoie au client
            System.out.println(" Le score = " + score);

            // insertion dans historique de la partie
            // pour la lisibilité du code j'ajoute une variable locale

            accesBdd.insererPartie(idC, user, score);

        } else {
            connector.writeOneString("false");  // envoie au client
            connector.writeOneString("false");  // envoie au client
        }

        System.out.println(" Fin de verif ");
    }

    private void newUserPartie() throws IOException {

        String user = connector.RedOneString();
        int nbColons = connector.RedOneInt();    // nb de choix de billes
        int nbColors = connector.RedOneInt();  // nb de choix de couleurs
        int nbTent = connector.RedOneInt();   // nb de tetatives max
        joueurs.put(user, new SecretCode(nbColons, nbColors, nbTent));
        System.out.print(" le combinaison de la partie est ");
        joueurs.get(user).printScode();

    }

    private void getUserStats() throws IOException {   // à finir 
        String user = connector.RedOneString();
        String[] outStats = accesBdd.getUStats(user);
        connector.sendUStats(outStats);

    }

    private void getStats() throws IOException {
        String[] outStats = null;
        
            int typeConf = connector.RedOneInt();
            switch (typeConf) {
                case 1:
                    outStats = accesBdd.getStats("Easy");
                    break;  // demande de stats (top 10) debutant
                case 2:
                    outStats = accesBdd.getStats("Medium");
                    break;  // demande de stats (top 10) debutant
                case 3:
                    outStats = accesBdd.getStats("Hard");
                    break;  // demande de stats (top 10) debutant
            }
        
        connector.sendStats(outStats);
    }

    // pour partie courante... 
    public int etablirScore(int nbTent, int numTourC) {

        return (100 - ((100 / nbTent) * numTourC));

    }
}   



/*
 * 
 * finally {
             
            try {                    
                connector.StopIN();                   
                }
           catch(IOException ioe){
                System.err.println(ioe);
                }
           try {
                connector.stopTCP();
                }
           catch(IOException ioe){
                System.err.println(ioe);
                } 
          }

 */